#!/usr/bin/python

# InnerSpace
# Copyright (C) 1999-2006 Phil Christensen
#
# $Id: code.py 157 2007-02-11 18:37:33Z phil $
#
# See LICENSE for details

"""
Code

Stability: mostly stable

Various methods to run and populate the environment of
'untrusted' code. This will hopefully soon integrate
the work in SaferPython.
"""

from inner.space.errors import *

def r_eval(code, environment=None):
	if not(environment):
		environment = {}
		import auth
		environment['caller'] = auth.get_current_user()
	return eval(code, globals(), environment)

def r_exec(code, environment):
	exec(code, environment)
	if("__result__" in environment):
		return environment["__result__"]
		
def _new_entity(name, parser):
	system = parser.registry.get(0)
	can_create = False
	if(system.has_callable_verb('approve_creation')):
		can_create = system.call_verb('approve_creation',
									  name,
									  parser.caller)
	from inner.space import auth
	current_user = auth.get_current_user()
	if(can_create or (not current_user) or current_user.is_wizard()):
		return parser.registry.new(name)
	else:
		raise PermissionError, "You are not allowed to create new objects."

def _sudo(owner, func, *args, **kwargs):
	from inner.space import auth
	auth.user_activate(owner)
	func(*args, **kwargs)
	auth.user_deactivate()
	
def get_environment(verb, parser):
	"""
	Get a dictionary object, suitable for passing to eval()/exec(),
	which contains the environment that verbs will be run in.
	"""
	result = parser.__dict__.copy()
	del result['registry']
	
	if('caller' in result and result['caller']):
		result['here'] = result['caller'].get_location()
		if(result['caller'].is_wizard()):
			result['load_verb']		= parser.registry.load_verb
			result['reload_verb']	= parser.registry.reload_verb
		if(result['caller'].is_programmer()):
			from inner.space import editors
			result['edit_verb'] = editors.edit_verb
			result['edit_property'] = editors.edit_property
			result['edit_acl'] = editors.edit_acl
			result['edit_entity'] = editors.edit_entity
		
	result['get_global'] 	= lambda(name): parser.registry.get(name)
	result['new_entity'] 	= lambda(name): _new_entity(name, parser)
	result['sudo'] 			= lambda(func): _sudo(verb.get_owner(), func)
	result['count_names'] 	= lambda(name): parser.registry.refs(name)
	result['get_pobj'] 		= lambda(prep): parser.get_pobj(prep)
	result['get_pobj_str'] 	= lambda(prep): parser.get_pobj_str(prep)
	result['has_pobj'] 		= lambda(prep): parser.has_pobj(prep)
	result['has_pobj_str'] 	= lambda(prep): parser.has_pobj_str(prep)
	result['get_dobj'] 		= lambda: parser.get_dobj()
	result['get_dobj_str'] 	= lambda: parser.get_dobj_str()
	result['has_dobj'] 		= lambda: parser.has_dobj()
	result['has_dobj_str'] 	= lambda: parser.has_dobj_str()
		
	result['system'] = parser.registry.get(0)
	
	return result
